package q222_countNodes;

import CommonClass.Common.TreeNode;
public class Solution {
    /**
     * 这里需要求完全二叉树的所有节点数量
     * 同样可以使用回溯或者直接层级遍历的方式来计算
     * 但是无法使用完全二叉树的特点（除了叶子层全满 并且叶子层从左往右排布）
     */
    public int countNodes(TreeNode root) {
        if(root == null){
            return 0;
        }
        int left = countLevel(root.left);
        int right = countLevel(root.right);
        if(left == right){
            // 1<<left = 1 * 2^left
            // 2<<n = 2 * 2^n
            return countNodes(root.right) + (1<<left);
        }else{
            return countNodes(root.left) + (1<<right);
        }
    }
    /*
    首先需要明确完全二叉树的定义：它是一棵空树或者它的叶子节点只出在最后两层，
    若最后一层不满则叶子节点只在最左侧。
    再来回顾一下满二叉的节点个数怎么计算，如果满二叉树的层数为h，则总节点数为：2^h - 1.
    那么我们来对 root 节点的左右子树进行高度统计，分别记为 left 和 right，有以下两种结果：
    1 - left == right。这说明，左子树一定是满二叉树，因为节点已经填充到右子树了，左子树必定已经填满了。
    所以左子树的节点总数我们可以直接得到，是 2^left - 1，加上当前这个 root 节点，则正好是 2^left。
    再对右子树进行递归统计。
    2 - left != right。说明此时最后一层不满，但倒数第二层已经满了，可以直接得到右子树的节点个数。
    同理，右子树节点 +root 节点，总数为 2^right。再对左子树进行递归查找。
     */
    private int countLevel(TreeNode root){
        int level = 0;
        while(root != null){
            level++;
            root = root.left;
        }
        return level;
    }

}
